package com.example.cloud.mygateway;

import jakarta.validation.constraints.NotEmpty;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;

import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: ws
 * Date: 2024-03-21
 * Time: 21:24
 * <p>
 * 自定义路由断言规则，能更好的服务业务
 * 必须实现的类  AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config>
 * 需求说明:自定义配置会员等级userTpye，按照钻/金/银和 yml 配置的会员等级，以适配是否可以访问
 * <p>
 * ...RoutePredicateFactory，... 会在 yml 配置中使用，注意名称
 * MyRoutePredicateFactory --> My
 * 2024-03-21T21:54:08.012+08:00  INFO 28712 --- [cloud-gateway] [           main] o.s.c.g.r.RouteDefinitionRouteLocator    : Loaded RoutePredicateFactory [My]
 */
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {

    /**
     * 配置短格式，方便 yml 的配置
     */
    @Override
    public List<String> shortcutFieldOrder() {
        return Collections.singletonList("userType");
    }

    public MyRoutePredicateFactory() {
        super(MyRoutePredicateFactory.Config.class);
    }

    /**
     * 模仿源码，写自己的路由断言类
     */
    @Validated // 校验参数所必需的注解
    public static class Config {
        @NotEmpty // 非空，需要配合 @Validated 注解使用
        private String userType; //钻、金、银等用户等级

        public String getUserType() {
            return userType;
        }

        public void setUserType(String userType) {
            this.userType = userType;
        }
    }

    /**
     * 根据 config 写路由断言的规则
     */
    @Override
    public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
        return new Predicate<ServerWebExchange>() {
            @Override
            public boolean test(ServerWebExchange serverWebExchange) {
                //检查request的参数里面，userType是否为指定的值，符合配置就通过
                String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
                if (userType == null) {
                    return false;
                }
                //如果说参数存在，就和config的数据进行比较
                return userType.equals(config.getUserType());
            }
        };
    }
}